unit uAstro;

interface

uses uDefs, cuVector;

{
STARS: Stars are given a "<name>"
PLANETS: Each Planet is named "<name> 1" etc
MOONS: Entities orbitting planets are moons and are named like so, "<name> 1 Moon 1"


Body Type Variables:
  Temperature
    Distance from Sun determins temperature.
    Effects water content
}

type
  tAstro = class( TObject )
  public
    astroName            : string;
    astroEmpireID        : integer; //Empire array ID.
    astroSolarID         : integer; //Solar System ID.
    astroCanBeCaptured   : boolean; //helps stop players capturing a blackhole.

    astroType            : enumObjectType; // Planet, star, moon, asteroidbelt, meteor etc
    astroClimate         : enumClimate;   // Climate effects the growth rate of the population.
    astroMineral         : enumMineral;   // Higher means more minerals.
    astroGravity         : enumGravity;   // Gravity effects production rates, high gravity slows production and low gravity speeds it up.
    astroSize            : integer;    // Size of the object increase maximum population and mineral extraction.

    astroDegreesPerWeek  : real;       // How Fast it travels around the central object, 0=no orbit
    astroInitialOrbit    : real;       // Where its start from the central line
    astroOrbitDistance   : integer;    // Distance from central object.
    astroOrbitID         : integer;    // Which Entity it is orbiting, -1 if not orbiting. May have solarsystems rotate around the galaxy core.

    astroLocation        : TVector2D; //Hold the x,y,z of a object position in the universe, based upon the Entity its orbitting.

    astroHealth          : integer; //Planets can be destroyed, but needs to lose all health in one turn.
    astroMaxHealth       : integer; //This maybe for capturing only.

    astroFleetsInOrbit   : integer;

    astroPopulation      : integer;
    astroMaxPopulation   : integer;
    astroGrowth          : integer;

    astroRevenue         : integer;
    astroSpending        : integer;

    procedure tickerPopulation();
    procedure setPopulation(Value:integer);

    constructor Create();
    destructor Destroy(); override;
    procedure resetAstro();

    function isPlanet():boolean;
    function isStar():boolean;

    procedure fleetEnterOrbit();
    procedure fleetLeaveOrbit();

    procedure OrbitRotation2D(CurrentAge:integer); //used for solarsystem view
    procedure OrbitRotation2DFromZero(CurrentAge:integer); //used for solarsystem view

    procedure linkEmpire(newEmpireID:integer);
  end;

implementation

uses SysUtils, cuDebug, Math, cuFuncs;

constructor tAstro.Create();
begin
  inherited;

  astroLocation := TVector2D.Create();
  resetAstro();
end;
destructor tAstro.Destroy();
begin
  resetAstro();
  FreeAndNil( astroLocation );

  inherited;
end;
procedure tAstro.resetAstro();
begin
  astroName            := '';
  astroEmpireID        := -1;
  astroSolarID         := -1;
  astroCanBeCaptured   := FALSE;

  astroType            := astroNONE;
  astroClimate         := climateNONE;
  astroMineral         := mineralNONE;
  astroGravity         := gravityNONE;
  astroSize            := 0;

  astroOrbitID         := -1;
  astroDegreesPerWeek  := 0;
  astroInitialOrbit    := 0;
  astroOrbitDistance   := 0;

  astroLocation.setVector2D( 0,0 );

  astroHealth          := 0;
  astroMaxHealth       := 0;

  astroFleetsInOrbit   := 0;

  astroPopulation      := 0;
  astroMaxPopulation   := 100;
  astroGrowth          := 1;

  astroRevenue         := 0;
  astroSpending        := 0;
end;

function TAstro.isPlanet():boolean; // I will do the rest when I get them working (blackhole, astroidbelt, etc).
begin
  if (astroType = objectPLANET) then
    result := TRUE
  else
    result := FALSE;
end;
function TAstro.isStar():boolean;
begin
  if (astroType = objectSTAR) then
    result := TRUE
  else
    result := FALSE;
end;

procedure TAstro.fleetEnterOrbit();
begin
  Inc( astroFleetsInOrbit );

  DevConsole.Print(LOG_DEBUG2, '[TAstro   ] Fleets Orbiting '+astroName+': '+IntToStr(astroFleetsInOrbit));
end;
procedure TAstro.fleetLeaveOrbit();
begin
  astroFleetsInOrbit := astroFleetsInOrbit - 1;

  DevConsole.Print(LOG_DEBUG2, '[TAstro   ] Fleets Orbiting '+astroName+': '+IntToStr(astroFleetsInOrbit));
end;

procedure TAstro.OrbitRotation2D(CurrentAge:integer);
var RotateAngle : real;
begin
  if (astroDegreesPerWeek <= 0) then Exit;

  //NewOrbit
  RotateAngle := astroDegreesPerWeek/100;

  astroLocation.RotateMatrix(RotateAngle);

  DevConsole.Print(LOG_DEBUG3, '[TMyApp   ] Orbit '+IntToStr(CurrentAge)+', Location: '+astroLocation.ToXY );
end;

procedure TAstro.OrbitRotation2DFromZero(CurrentAge:integer);
begin
  if (astroDegreesPerWeek <= 0) then Exit;

  astroLocation.setVector2D( 0, astroOrbitDistance ); //This resets the astros location to [0,orbitDistance]

  astroLocation.RotateMatrixUsingTime( astroDegreesPerWeek, astroInitialOrbit, CurrentAge );

  DevConsole.Print(LOG_DEBUG3, '[TMyApp   ] Orbit '+IntToStr(CurrentAge)+', Location: '+astroLocation.ToXY );
end;

procedure TAstro.tickerPopulation();
begin
  if (astroPopulation < astroMaxPopulation) then
    Inc( astroPopulation, astroGrowth );

  if (astroPopulation > astroMaxPopulation) then
    astroPopulation := astroMaxPopulation;
end;

procedure TAstro.setPopulation(Value:integer);
begin
  astroPopulation := Value;
end;

procedure TAstro.linkEmpire(newEmpireID:integer);
begin
  DevConsole.Print(LOG_DEBUG2, '[TAstro   ] linkEmpire - Linking empire '+IntToStr(newEmpireID));

  astroEmpireID := newEmpireID;
end;

end.
